<!-- 基础表格组件 -->

<!-- 属性 -->
<!-- 配置名称 | 类型 | 用途 | 返回值 | 默认值 | 必填 | 说明 -->
<!-- init-table-method     | Function | 初始化表格数据 | Promise<any> | null                  | * | 无 -->
<!-- condition-method      | Function | 初始化表格数据 | Object       | () => { return null } | - | 无 -->
<!-- refresh-key           | String   | 主动刷新表格   | -            | 'xxxxxx'              | - | 无 -->
<!-- storage-condition     | Boolean  | 缓存搜索条件   | -            | false                 | - | 如果需要实现搜索条件回填，需要手动实现restore-search事件 -->
<!-- attributes            | Object   | 其他属性      | -            | {}                    | - | 无 -->

<!-- 事件 -->
<!-- 无 -->

<!-- 插槽 -->
<!--
  #default: 各个列的配置
-->
<script setup lang="ts">
import { onMounted, ref, watch } from 'vue'
import { useRoute } from 'vue-router'
import { useRestoreSearch } from '@st/hooks/useRestoreSearch'

interface Props {
  initTableMethod: (option: any) => Promise<any>
  conditionMethod?: () => any
  refreshKey?: string
  storageCondition?: boolean
  attributes?: any
}

const props = withDefaults(defineProps<Props>(), {
  conditionMethod: () => {
    return null
  },
  refreshKey: `${new Date().getTime()}`,
  storageCondition: false,
  attributes: () => {
    return {}
  }
})

const emit = defineEmits<{
  (e: 'selection-change', val: any): void
  (e: 'page-change', val: any): void
  (e: 'data-change', val: any): void
  (e: 'restore-search', val: any): void
  (e: 'loading-change', val: any): void
}>()

const bindAttributes = {}
Object.assign(bindAttributes, props.attributes)

const bindPaginationHeight = ref('80px')

const baseTableRef = ref()

// 缓存搜索项
const route = useRoute()
const moduleKey = route.path
const { setSearchStorage, setPageNumStorage, setPageSizeStorage, restoreSearchStorage, restorePageNumStorage, restorePageSizeStorage } =
  useRestoreSearch(moduleKey)

const pageNum = ref(1)
watch(pageNum, (newVal) => {
  emit('page-change', {})
  if (props.storageCondition) {
    setPageNumStorage(newVal)
  }
  initTableData(true)
})
const pageSize = ref(restorePageSizeStorage())
watch(pageSize, (newVal) => {
  emit('page-change', {})
  if (props.storageCondition) {
    setPageSizeStorage(newVal)
  }
  initTableData(true)
})
const total = ref(0)

const loading = ref(false)

const tableData = ref<Array<any>>([])

// 排序相关
let sortitem: any = null
const handleSortChange = ({ prop, order }: any) => {
  // const target = sortableArr.find((item: any) => item.prop === prop)
  // if (target) {
  //   target.order = order
  // } else {
  //   sortableArr.push({ prop, order })
  // }
  sortitem = { prop, order }
  initTableData()
}

const initTableData = (initiative = false) => {
  loading.value = true
  // 初始化页数
  if (props.storageCondition && !initiative) {
    // 如果是被动刷新页面，则设置为缓存的页数
    pageNum.value = restorePageNumStorage()
  }
  const option: Record<string, any> = {
    current: pageNum.value,
    size: pageSize.value
  }
  // 如果是被动刷新页面，则取出缓存的搜索条件
  let reconds = {}
  if (props.storageCondition && !initiative) {
    reconds = restoreSearchStorage()
    emit('restore-search', reconds)
  }
  // 页面发送来的筛选条件
  const conds = props.conditionMethod()
  if (props.storageCondition) {
    setSearchStorage(conds)
  }
  // 组织最终筛选条件
  const conditions: any = {}
  Object.assign(conditions, reconds, conds)
  if (conditions) {
    Object.keys(conditions).map((key) => {
      option[key] = conditions[key]
    })
  }
  // 组织排序条件
  if (sortitem) {
    if (sortitem.order) {
      option[sortitem.prop] = sortitem.order
    }
  }
  // 获取数据
  props
    .initTableMethod(option)
    .then((res) => {
      if (res) {
        if (parseInt(res.pages)) {
          if (option.current <= parseInt(res.pages)) {
            total.value = parseInt(res.total)
            tableData.value = res.records
            emit('data-change', res.records)
          }
        } else {
          total.value = 0
          tableData.value = []
          emit('data-change', [])
        }
      } else {
        total.value = 0
        tableData.value = []
      }
    })
    .finally(() => {
      loading.value = false
    })
}

const handleSelectionChange = (val: any) => {
  emit('selection-change', val)
}

const refresh = () => {
  pageNum.value = 1
  sortitem = null
  baseTableRef.value.clearSort()
  initTableData(true)
}

const refreshStay = () => {
  initTableData(true)
}

// 主动刷新表单逻辑
watch(
  () => props.refreshKey,
  () => {
    refresh()
  }
)

// loading状态通知
watch(loading, (newVal) => {
  emit('loading-change', newVal)
})

defineExpose({
  baseTableRef,
  refresh,
  refreshStay
})

onMounted(() => {
  initTableData()
})
</script>

<template>
  <div class="base-table-wrapper">
    <div class="table-container">
      <el-table
        ref="baseTableRef"
        v-loading="loading"
        :data="tableData"
        style="width: 100%"
        height="100%"
        v-bind="bindAttributes"
        @selection-change="handleSelectionChange"
        @sort-change="handleSortChange"
      >
        <slot></slot>
      </el-table>
    </div>
    <div class="pagination-container">
      <el-pagination v-model:current-page="pageNum" v-model:page-size="pageSize" background layout="total, sizes, prev, pager, next" :total="total" />
    </div>
  </div>
</template>

<style lang="scss" scoped>
.base-table-wrapper {
  @include rect(100%, 100%);
  .table-container {
    .el-table {
      --el-table-header-text-color: rgba(48, 49, 51, 1) !important;
      --el-table-header-bg-color: rgba(245, 247, 249, 1) !important;
      :deep(.el-table__inner-wrapper::before) {
        background-color: rgba(255, 255, 255, 0);
      }
      :deep(.el-table__cell) {
        padding: 12px 0;
      }
    }
    @include rect(100%, calc(100% - v-bind(bindPaginationHeight)));
  }
  .pagination-container {
    @include rect(100%, v-bind(bindPaginationHeight));
    @include flex(row, flex-end, center);
  }
}
</style>
